package com.stx.jeepay.payment.controller.division;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.stx.jeepay.core.entity.MchDivisionReceiverEntity;
import com.stx.jeepay.core.entity.MchDivisionReceiverGroupEntity;
import com.stx.jeepay.core.entity.PayOrderDivisionRecordEntity;
import com.stx.jeepay.core.entity.PayOrderEntity;
import com.stx.jeepay.core.enums.CS;
import com.stx.jeepay.core.expection.BizException;
import com.stx.jeepay.core.model.ApiRes;
import com.stx.jeepay.core.mq.model.PayOrderDivisionMQ;
import com.stx.jeepay.core.service.MchDivisionReceiverGroupService;
import com.stx.jeepay.core.service.MchDivisionReceiverService;
import com.stx.jeepay.core.service.PayOrderService;
import com.stx.jeepay.payment.controller.ApiController;
import com.stx.jeepay.payment.model.MchAppConfigContext;
import com.stx.jeepay.payment.rqrs.division.PayOrderDivisionExecRQ;
import com.stx.jeepay.payment.rqrs.division.PayOrderDivisionExecRS;
import com.stx.jeepay.payment.rqrs.msg.ChannelRetMsg;
import com.stx.jeepay.payment.service.ConfigContextQueryService;
import com.stx.jeepay.payment.service.PayOrderDivisionProcessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 发起分账请求
 */
@Slf4j
@RestController
public class PayOrderDivisionExecController extends ApiController {
    @Autowired
    private ConfigContextQueryService configContextQueryService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private MchDivisionReceiverService mchDivisionReceiverService;
    @Autowired
    private MchDivisionReceiverGroupService mchDivisionReceiverGroupService;
    @Autowired
    private PayOrderDivisionProcessService payOrderDivisionProcessService;

    /**
     * 分账执行
     **/
    @PostMapping("/api/division/exec")
    public ApiRes exec() {
        PayOrderDivisionExecRQ bizRQ = getRQByWithMchSign(PayOrderDivisionExecRQ.class);
        try {
            if (StringUtils.isAllEmpty(bizRQ.getMchOrderNo(), bizRQ.getPayOrderId())) {
                throw new BizException("mchOrderNo 和 payOrderId不能同时为空");
            }
            PayOrderEntity payOrder =
                    payOrderService.queryMchOrder(bizRQ.getMchNo(), bizRQ.getPayOrderId(), bizRQ.getMchOrderNo());
            if (payOrder == null) {
                throw new BizException("订单不存在");
            }

            if (payOrder.getState() != PayOrderEntity.STATE_SUCCESS
                    || payOrder.getDivisionState() != PayOrderEntity.DIVISION_STATE_UNHAPPEN
                    || payOrder.getDivisionMode() != PayOrderEntity.DIVISION_MODE_MANUAL) {
                throw new BizException("当前订单状态不支持分账");
            }
            List<PayOrderDivisionMQ.CustomerDivisionReceiver> receiverList = null;

            // 不使用默认分组 需要转换每个账号的信息
            if (bizRQ.getUseSysAutoDivisionReceivers() != CS.YES && !StringUtils.isEmpty(bizRQ.getReceivers())) {
                receiverList = JSON.parseArray(bizRQ.getReceivers(), PayOrderDivisionMQ.CustomerDivisionReceiver.class);
            }

            // 校验账号是否合法
            this.checkReceiverList(receiverList, payOrder.getIfCode(), bizRQ.getMchNo(), bizRQ.getAppId());

            // 商户配置信息
            MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(bizRQ.getMchNo(), bizRQ.getAppId());
            if (mchAppConfigContext == null) {
                throw new BizException("获取商户应用信息失败");
            }

            // 处理分账请求
            ChannelRetMsg channelRetMsg =
                    payOrderDivisionProcessService.processPayOrderDivision(payOrder.getPayOrderId(), bizRQ.getUseSysAutoDivisionReceivers(), receiverList, false);
            PayOrderDivisionExecRS bizRS = new PayOrderDivisionExecRS();
            bizRS.setState(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS ? PayOrderDivisionRecordEntity.STATE_SUCCESS : PayOrderDivisionRecordEntity.STATE_FAIL);
            bizRS.setChannelBatchOrderId(channelRetMsg.getChannelOrderId());
            bizRS.setErrCode(channelRetMsg.getChannelErrCode());
            bizRS.setErrMsg(channelRetMsg.getChannelErrMsg());

            return ApiRes.okWithSign(bizRS, mchAppConfigContext.getMchApp().getAppSecret());
        } catch (BizException e) {
            return ApiRes.customFail(e.getMessage());
        } catch (Exception e) {
            log.error("系统异常：{}", e);
            return ApiRes.customFail("系统异常");
        }
    }

    /**
     * 检验账号是否合法
     **/
    private void checkReceiverList(List<PayOrderDivisionMQ.CustomerDivisionReceiver> receiverList,
                                   String ifCode, String mchNo, String appId) {
        if (receiverList == null || receiverList.isEmpty()) {
            return;
        }

        Set<Long> receiverIdSet = new HashSet<>();
        Set<Long> receiverGroupIdSet = new HashSet<>();

        for (PayOrderDivisionMQ.CustomerDivisionReceiver receiver : receiverList) {
            if (receiver.getReceiverId() != null) {
                receiverIdSet.add(receiver.getReceiverId());
            }

            if (receiver.getReceiverGroupId() != null) {
                receiverGroupIdSet.add(receiver.getReceiverGroupId());
            }

            if (receiver.getReceiverId() == null && receiver.getReceiverGroupId() == null) {
                throw new BizException("分账用户组： receiverId 和 与receiverGroupId 必填一项");
            }

            if (receiver.getDivisionProfit() != null) {
                // 异常情况 费率小于0% 或者高于100%
                if (receiver.getDivisionProfit().compareTo(BigDecimal.ZERO) < 0) {
                    throw new BizException("分账用户receiverId=[" + (receiver.getReceiverId() == null ? "" : receiver.getReceiverId()) + "]," +
                            "receiverGroupId=[" + (receiver.getReceiverGroupId() == null ? "" : receiver.getReceiverGroupId()) + "] 分账比例不得小于0%");
                }

                if (receiver.getDivisionProfit().compareTo(BigDecimal.ONE) > 0) {
                    throw new BizException("分账用户receiverId=[" + (receiver.getReceiverId() == null ? "" : receiver.getReceiverId()) + "]," +
                            "receiverGroupId=[" + (receiver.getReceiverGroupId() == null ? "" : receiver.getReceiverGroupId()) + "] 分账比例不得高于100%");
                }
            }

            if (!receiverIdSet.isEmpty()) {
                int receiverCount = mchDivisionReceiverService.count(new LambdaQueryWrapper<MchDivisionReceiverEntity>()
                        .in(MchDivisionReceiverEntity::getReceiverId, receiverIdSet)
                        .eq(MchDivisionReceiverEntity::getMchNo, mchNo)
                        .eq(MchDivisionReceiverEntity::getAppId, appId)
                        .eq(MchDivisionReceiverEntity::getIfCode, ifCode)
                        .eq(MchDivisionReceiverEntity::getState, CS.YES));
                if (receiverCount != receiverIdSet.size()) {
                    throw new BizException("分账[用户]中包含不存在或渠道不可用账号，请更改");
                }
            }

            if (!receiverGroupIdSet.isEmpty()) {
                int receiverGroupCount = mchDivisionReceiverGroupService.count(new LambdaQueryWrapper<MchDivisionReceiverGroupEntity>()
                        .in(MchDivisionReceiverGroupEntity::getReceiverGroupId, receiverGroupIdSet)
                        .eq(MchDivisionReceiverGroupEntity::getMchNo, mchNo));
                if (receiverGroupCount != receiverGroupIdSet.size()) {
                    throw new BizException("分账[账号组]中包含不存在或不可用组，请更改");
                }
            }
        }
    }
}
